/* Copyright © 2010 LPRM
Universidade Federal do Espírito Santo - RNP-GT CWTools

This file is part of JoinUs!.

JoinUs! is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

JoinUs! is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with JoinUs!. If not, see <http://www.gnu.org/licenses/>. */
package android.isisufes.home2;

import java.util.Calendar;

import android.app.Activity;
import android.app.DatePickerDialog;
import android.content.Intent;
import android.database.sqlite.SQLiteDatabase;
import android.isisufes.R;
import android.isisufes.home.map.AreaChooser;
import android.isisufes.util.ServerCom;
import android.os.Bundle;
import android.text.format.Time;
import android.util.Log;
import android.view.View;
import android.widget.DatePicker;
import android.widget.EditText;
import android.widget.TimePicker;
import android.widget.Toast;
import android.widget.TimePicker.OnTimeChangedListener;

public class CampaignCreateActivity extends Activity {

	String name;
	String description;
	int year, day, month;
	int hour, minute;

	private Bundle fromUserChoser = null;
	private Bundle fromAreaChoser = null;
	private static final int CHOOSE_USERS = 1;
	private static final int CHOOSE_AREA = 2;
	
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);

		Log.d("CampaignCreateActivity", "onCreate");
		this.setContentView(R.layout.camp_creator);
		
		// Inicializa os campos com a data atual.
		// É necessário caso o usuário não altere a data inicial do calendário.
		Calendar calendar = Calendar.getInstance();
		this.year = calendar.get(Calendar.YEAR);
		this.month = 1 + calendar.get(Calendar.MONTH);
		this.day = calendar.get(Calendar.DAY_OF_MONTH);
		
		setUpTimer();
	}

	private void setUpTimer() {
		// Inicializa a hora e minuto.
		// É necessário caso o usuário não altere a hora inicial do timepicker.
		Time time = new Time();
		time.setToNow();
		this.hour = time.hour;
		this.minute = time.minute;
		
		// Ajusta a hora; não sei se é necessário, mas garante a consistência.
		TimePicker tp = (TimePicker) this.findViewById(R.id.time_cc);
		tp.setCurrentHour(this.hour);
		tp.setCurrentMinute(this.minute);
		
		OnTimeChangedListener listener = new OnTimeChangedListener() {
			public void onTimeChanged(TimePicker view, int hourOfDay, int minute) {
				CampaignCreateActivity.this.minute = minute;
				CampaignCreateActivity.this.hour = hourOfDay;
			}
		};
		tp.setOnTimeChangedListener(listener);
	}

	/**
	 * onClick do botão de seleção de data de término.
	 * @param view
	 */
	public void chooseExpireDateOnClick(View view) {
		/*
		 * Amarra a exibição de um DatePickerDialog ao botão para seleção de data
		 * para término da campanha.
		 * */

		final DatePickerDialog.OnDateSetListener mDateSetListener =
			new DatePickerDialog.OnDateSetListener() {
			public void onDateSet(DatePicker view, int year, int monthOfYear,
					int dayOfMonth) {
				// TODO: Não permitir uma data no passado.
				CampaignCreateActivity.this.year = year;
				// Somar 1 ao mês porque este calendário conta a partir de
				// Janeiro como mês 0.
				CampaignCreateActivity.this.month = 1 + monthOfYear;
				CampaignCreateActivity.this.day = dayOfMonth;
				Log.d("CampCreate", "New campaign expiration date set.");
			}
		};

		// Inicializa o diálogo de seleção também com a data anterior;
		// inicialmente a data atual.
		final DatePickerDialog dialog = new DatePickerDialog(
				this, mDateSetListener,
				this.year, this.month -1, this.day);
		dialog.show();
	}

	/**
	 * onClick do botão de seleção de usuários participantes.
	 * @param view
	 */
	public void chooseUsersOnClick(View view) {
		Log.d("CampaignCreateActivity", "onClick do botão de seleção de usuários; " +
				"iniciando a activity UserChooser.");
		Intent i = new Intent();
		i.setClass(this, UserChooser.class);
		Bundle extra = new Bundle();
		extra.putString("username", this.getIntent().getExtras().getString("username"));
		i.putExtras(extra);
		startActivityForResult(i, CHOOSE_USERS);
	}

	/**
	 * onClick do botão de seleção de área.
	 * @param view
	 */
	public void chooseAreaOnClick(View view) {
		Log.d("CampaignCreateActivity", "Iniciando activity AreaChooser.");
		Intent i = new Intent(getApplicationContext(), AreaChooser.class);
		startActivityForResult(i,CHOOSE_AREA);
	}
	
	@Override
	protected void onActivityResult(int requestCode, int resultCode, Intent data) {
		super.onActivityResult(requestCode, resultCode, data);
		if (requestCode == CHOOSE_USERS){
			if (resultCode != RESULT_OK || data == null) return;
			fromUserChoser = data.getExtras();
		}
		if (requestCode == CHOOSE_AREA){
			if (resultCode != RESULT_OK || data == null) return;
			fromAreaChoser = data.getExtras();
		}
		// TODO: Adicionar os usuários/comunidades aos já selecionados
		// anteriormente ao invés de sobreescrever o bundle.
	}
	
	/**
	 * onClick do botão de confirmação da criação de campanha.
	 * @param view
	 */
	public void createOnClick(View view) {
		Log.d("CampaignCreateActivity", "createOnClick: Botão de confirmação da criação da campanha.");

		name = ((EditText) this.findViewById(R.id.edit_cc)).getText().toString().trim().replaceAll("\'|\"", "''");
		if (name.length() == 0) {
			Toast.makeText(this, "Campaign name cannot be empty.", Toast.LENGTH_SHORT).show();
			return;
		}
		
		description = ((EditText) this.findViewById(R.id.desc_cc)).getText().toString().trim().replaceAll("\'|\"", "''");
		if (description.length() == 0) {
			Toast.makeText(this, "Please provide a description.", Toast.LENGTH_SHORT).show();
			return;
		}
		
		Bundle bundle = this.getIntent().getExtras();
		String username = bundle.getString("username");
		String password = bundle.getString("password");
		String fullname = bundle.getString("fullname");
		Log.d("CampaignCreateActivity", "Usuário autenticado, username: " + username + ", password: "
			+ password.replaceAll(".", "*") + ", fullname: " + fullname);
		
		int x_area, y_area, x2, y2;
		x_area = fromAreaChoser.getInt("lat1");
		y_area = fromAreaChoser.getInt("lon1");
		x2 = fromAreaChoser.getInt("lat2");
		y2 = fromAreaChoser.getInt("lon2");
		
		/*double dLat = Math.toRadians(x2-x_area);
	    double dLon = Math.toRadians(y2-y_area);
	    double a = Math.sin(dLat/2)*Math.sin(dLat/2) + Math.cos(Math.toRadians(x_area)) * Math.cos(Math.toRadians(x2))*Math.sin(dLon/2) * Math.sin(dLon/2);
	    double c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a)); 
		
		Double r = 6378.1 * c;
		Log.d("CampaignCreateActivity","Raio original: "+r);*/
		Double r = Math.sqrt(Math.pow(x_area - x2, 2) + Math.pow(y_area - y2, 2));
		int radius = r.intValue();
		Log.d("CampaignCreateActivity", "Regiao da campanha: (" + x_area + ", " + y_area + "), raio " + radius);
		
		int isPublic = 1;
		String[] idsContacts = null;
		String[] idsCommunities = null;
		
		// Constrói o vetor de contatos/comunidades a serem convidadas baseado
		// no retorno de UserChooser, this.fromUserChooser.
		if (fromUserChoser != null) {
			int n;
			n = fromUserChoser.getInt("ncont", 0);
			if (n > 0) {
				Log.d("CampaignCreateActivity", "Contatos foram selecionados para camapanha, no total: " + n);
				isPublic = 0;
				idsContacts = new String[n];
				for (int i = 0; i < n; ++i) {
					long id = fromUserChoser.getLong("cont" + i);
					idsContacts[i] = Long.toString(id);
					Log.d("CampaignCreateActivity", "Contato convidado com ID " + id);
				}
			}
			n = fromUserChoser.getInt("ncomm", 0);
			if (n > 0) {
				Log.d("CampaignCreateActivity", "Comunidades foram selecionados para camapanha, no total: " + n);
				isPublic = 0;
				idsCommunities = new String[n];
				for (int i = 0; i < n; ++i) {
					long id = fromUserChoser.getLong("comm" + i);
					idsCommunities[i] = Long.toString(id);
					Log.d("CampaignCreateActivity", "Contato convidado com ID " + id);
				}
			}
		}
		
		// Caso não saibamos com antecedência o número de parâmetros.
		/*if (fromUserChooser != null && fromUserChooser.size() > 0) {
			int n = 0;
			int t = fromUserChooser.size();
			
			idsContacts = new String[t];
			while (true) {
				long item = fromUserChooser.getLong("cont" + n, -1);
				if (item != -1) {
					idsContacts[n++] = Long.toString(item);
					Log.d("CampaignCreateActivity", "Invited contact with ID " + item);
				} else break;
			}
			if (n > 0) isPublic = 0;
			else idsContacts = null;
			
			if (t - n > 0) {
				idsCommunities = new String[t - n];
				n = 0;
				while (true) {
					long item = fromUserChooser.getLong("comm", -1);
					if (item != -1) {
						idsCommunities[n++] = Long.toString(item);
						Log.d("CampaignCreateActivity", "Invited community with ID " + item);
					} else break;
				}
				if (n > 0) isPublic = 0;
				else idsCommunities = null;
			}
		}*/

		// Envia a requisição para criar a campanha no servidor.
		int campId = ServerCom.CreteCampAction(username, password, username,
				x_area, y_area, radius, description,
				year + "-" + month + "-" + day + " " + hour + ":" + minute,
				name, isPublic);

		Log.d("CampaignCreateActivity", "Campanha criada no servidor com ID " + campId);
		
		// Envia os convites.
		if (idsContacts != null) ServerCom.InviteContact(idsContacts, campId);
		if (idsCommunities != null) ServerCom.InviteCommu(idsCommunities, campId);

		// Salva no banco de dados local.
		SQLiteDatabase database = this.openOrCreateDatabase("homedb", MODE_PRIVATE, null);
		database.execSQL("INSERT INTO activeCamp (campName, id, lat, lon, radius, user, authorName, desc, expDate, status, public) " +
				"VALUES ('" + name + "',"
				+ campId + ",'"
				+ x_area + "','"
				+ y_area + "','"
				+ radius + "','"
				+ username + "','"
				+ fullname + "','"
				+ description + "','"
				+ year + "-" + month + "-" + day + " " + hour + ":" + minute + ":00', 0,'"
				+ isPublic +"');");
		database.close();
		
		Toast.makeText(this, "Campaign created.", Toast.LENGTH_SHORT).show();
		
		Log.d("CampaignCreateActivity", "Campanha criada, finalizando activity.");
		// Termina esta activity.
		this.finish();
	}
}